<template>
    <ARow>
        <div class="custom-draggable-container">
            <div class="container-left">
                <a-collapse v-model="activeKey">
                    <a-collapse-panel key="1" header="基础表单组件">
                        <VueDraggable
                            v-model="elFields"
                            class="draggable-container"
                            animation="150"
                            ghostClass="ghost"
                            :group="{
                                name: 'people',
                                pull: 'clone',
                                put: false,
                            }"
                            :sort="false"
                            :clone="clone"
                        >
                            <div
                                v-for="item in elFields"
                                :key="item.el_key"
                                class="draggable-container-item"
                            >
                                {{ item.label }}
                            </div>
                        </VueDraggable>
                    </a-collapse-panel>
                </a-collapse>
            </div>
            <div class="container-center">
                {{ list2 }}
                <VueDraggable
                    v-model="list2"
                    animation="150"
                    group="people"
                    ghostClass="ghost"
                    :scroll="true"
                    class="draggable-box"
                >
                    <div
                        v-for="item in list2"
                        :key="item.el_key"
                        :class="['el-item', curId === item.id ? 'active' : '']"
                        @click="onElClick(item)"
                    >
                        <div class="el-item-label">
                            <span v-if="item.required" class="required">*</span>
                            {{ item.label }}
                        </div>
                        <div class="el-item-tag">
                            <component
                                :is="item.el"
                                v-bind="{
                                    ...item.attrs,
                                    placeholder:
                                        item.placeholder ||
                                        (item.attrs &&
                                            item.attrs.placeholder) ||
                                        item.label ||
                                        item.key,
                                }"
                                v-model="formData[item.key]"
                                :style="{ width: item.width ? `${item.width}px` : '100%' }"
                            />
                        </div>
                        <div
                            v-if="curId === item.id"
                            class="el-item-action"
                            @click="delClick($event, item)"
                        >
                            <a-icon type="delete" />
                        </div>
                        <div class="el-item_key">
                            <span>数据字段:{{ item.key }}</span>
                        </div>
                    </div>
                </VueDraggable>
            </div>
            <div class="container-right">
                <a-tabs default-active-key="1">
                    <a-tab-pane key="1" tab="控件属性配置">
                        <div v-if="selectElRow && selectElRow.id">
                            <div class="el-attribute">
                                <span>标签名:</span>
                                <AInput v-model="selectElRow.label" />
                            </div>
                            <div class="el-attribute">
                                <span>数据字段:</span>
                                <AInput v-model="selectElRow.key" />
                            </div>
                            <div class="el-attribute">
                                <span>占位符:</span>
                                <AInput
                                    v-model="selectElRow.attrs.placeholder"
                                />
                            </div>
                            <div class="el-attribute">
                                <span>宽度(px):</span>
                                <AInput
                                    v-model="selectElRow.width"
                                    type="number"
                                />
                            </div>
                            <div
                                v-if="
                                    selectElRow.type === 'text' ||
                                    selectElRow.type === 'number'
                                "
                                class="el-attribute"
                            >
                                <span>输入框类型:</span>
                                <AInput v-model="selectElRow.attrs.type" />
                            </div>
                            <div
                                v-if="selectElRow.type === 'select'"
                                class="el-attribute"
                            >
                                <span>下拉框模拟数据:</span>

                                <template
                                    v-for="(item, index) in selectElRow.attrs
                                        .options"
                                >
                                    <div :key="index" class="selectOptions">
                                        <AInput
                                            v-model="item.label"
                                            style="margin-right: 10px"
                                            placeholder="名称"
                                        />
                                        <AInput
                                            v-model="item.value"
                                            placeholder="值"
                                        />
                                    </div>
                                </template>
                                <span class="add-btn" @click="add"
                                    >添加mock数据</span
                                >
                            </div>
                            <div class="el-attribute">
                                <span>是否必填:</span>
                                <ACheckbox v-model="selectElRow.required" />
                                <AInput
                                    v-model="selectElRow.rules"
                                    placeholder="校验提示信息(可填可不填)"
                                />
                            </div>
                        </div>
                    </a-tab-pane>
                    <a-tab-pane key="2" tab="Tab 2" force-render>
                        Content of Tab Pane 2
                    </a-tab-pane>
                </a-tabs>
            </div>
        </div>
        <ARow style="margin-top: 40px" type="flex" justify="center">
            <ASpace>
                <AButton type="primary" @click="previewClick">预览</AButton>
                <AButton type="primary" @click="exportJSON"
                    >导出json文件</AButton
                >
                <AButton type="primary" @click="getCode">生成代码</AButton>
            </ASpace>
        </ARow>

        <!-- 展示 json 数据 -->
        <ModelData ref="jsonRef" />

        <!-- 预览组件 -->
        <PreviewForm ref="previeRef" />

        <!-- 生成代码 -->
        <GenerateCode ref="codeRef" />
    </ARow>
</template>

<script>
import { VueDraggable } from "vue-draggable-plus";
import { fields } from "./config";
import { nanoid } from "nanoid";
import ModelData from "./components/ModelData.vue";
import PreviewForm from "./components/PrivewForm.vue";
import GenerateCode from "./components/GenerateCode.vue";
export default {
    components: {
        VueDraggable,
        ModelData,
        PreviewForm,
        GenerateCode,
    },
    data() {
        return {
            fields,
            list2: [],
            activeKey: "",
            curId: "",
            drawerVisible: false,
            placement: "right",
            selectElRow: {
                attrs: { type: "", options: [] },
            },
            formData: {},
        };
    },
    computed: {
        elFields() {
            return this.fields.map((item) => ({
                ...item,
                id: nanoid(6),
            }));
        },
    },
    watch: {
        selectElRow: {
            handler(val) {
                setTimeout(() => {
                    this.list2 = this.list2.map((item) => {
                        return item.id === val.id ? val : item;
                    });
                }, 2000);
            },
            deep: true,
        },
    },
    methods: {
        clone(element) {
            const row = {
                ...element,
                label: `${element.label}-clone-${nanoid(5)}`,
                el_key: `自定义${nanoid(7)}`,
                el: element.el,
                attrs: element.attrs || {},
                id: element.id + nanoid(2) + element.el_key,
                key: nanoid(3),
                type: element.type || "",
                width: element.width,
                required: element.required || false,
            };
            this.onElClick(row);
            this.selectElRow = { ...row };
            return row;
        },
        onElClick(item) {
            if (!item.id) return;
            this.curId = item.id;
            this.selectElRow = { ...item };
        },
        delClick(e, item) {
            e.stopPropagation();
            this.list2 = this.list2.filter((x) => x.id !== item.id);
            const info = this.list2[this.list2.length - 1];
            if (!info) {
                this.selectElRow = {};
            }
            // 重新赋值
            this.onElClick(info || {});
        },
        add() {
            this.selectElRow?.attrs?.options.push({
                label: nanoid(1),
                value: nanoid(3),
            });
        },
        exportJSON() {
            this.$refs.jsonRef.show(this.list2);
        },
        previewClick() {
            const fieldsArr = this.getFields(this.list2)
            this.$refs.previeRef.show(fieldsArr);
        },
        getCode() {
            const fieldsArr = this.getFields(this.list2)
            this.$refs.codeRef.showModel(fieldsArr);
        },
        getFields(list = []) {
            return list.map((item) => ({
                key: item.key,
                label: item.label,
                el: item.el,
                attrs: item.attrs,
                rules: item.rules
                    ? [
                          {
                              message: item.rules,
                              trigger: "change",
                              required: true,
                          },
                      ]
                    : [],
                required: item.required,
                width: item.width
            }));
        },
    },
};
</script>

<style lang="less" scoped>
.cursor-move {
    height: 40px;
    margin-bottom: 10px;
    &:hover {
        cursor: move;
    }
}
.container {
    width: 100%;
    height: 900px;
    overflow: auto;
    border: 1px solid #ccc;
}
.custom-draggable-container {
    display: flex;
    align-items: center;
    box-sizing: border-box;

    .container-left {
        width: 300px;
        min-height: 80vh;
        overflow: auto;
        background-color: #fafafa;
        .draggable-container {
            display: flex;
            flex-wrap: wrap;
            &-item {
                height: 36px;
                width: 124px;
                border: 1px solid transparent;
                cursor: move;
                box-shadow: 1px 0 0 0 #ccc, 0 1px 0 0 #ccc, 1px 1px 0 0 #ccc,
                    inset 1px 0 0 0 #ccc, inset 0 1px 0 0 #ccc;
                margin: 3px;
                display: flex;
                align-items: center;
                justify-content: center;
            }
        }
    }
    .container-center {
        flex: 1;
        min-height: 80vh;
        overflow: auto;
        border: 1px solid #ccc;
        margin-left: 20px;
        padding: 10px;
        .draggable-box {
            min-height: 400px;
            max-height: 80vh;
            overflow-y: auto;
            padding-top: 10px;
            .el-item {
                display: flex;
                align-items: center;
                width: 100%;
                cursor: move;
                padding: 6px;
                position: relative;
                margin-bottom: 10px;
                &-label {
                    width: 180px;
                    display: flex;
                    align-items: center;
                    .required {
                        color: #fe2d28;
                        padding-right: 6px;
                    }
                }
                &-tag {
                    flex: 1;
                }
                &-action {
                    height: 30px;
                    border-radius: 4px;
                    position: absolute;
                    top: -10px;
                    right: 10px;
                    z-index: 99;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    padding-left: 10px;
                    padding-right: 10px;
                    background: #13c2c2;
                    &:hover {
                        cursor: pointer;
                    }
                }
                &_key {
                    position: absolute;
                    bottom: -10px;
                    right: 10px;
                }
            }
        }
    }
    .active {
        background: rgba(19, 194, 194, 0.2);
        &::before {
            content: "";
            height: 5px;
            width: 100%;
            background: #13c2c2;
            position: absolute;
            top: 0;
            right: 0;
            z-index: 2;
            -webkit-transition: all 0.3s;
            transition: all 0.3s;
        }
    }

    .container-right {
        width: 300px;
        min-height: 80vh;
        overflow: auto;
        margin-left: 20px;
        border: 1px solid #ccc;
        .el-attribute {
            padding: 10px;
            .add-btn {
                color: #13c2c2;
                cursor: pointer;
            }
        }
        .selectOptions {
            display: flex;
            align-items: center;
            margin-bottom: 3px;
        }
    }
}
</style>
